Controlling Output

Let's switch topics for a moment. Thus far, we have been merely displaying data using the print statement and its default characteristics = namely, printing a space between components and ending the statement with a line break. We can control this behavior.

Item Separator

We have seen that you can print multiple literal constants and variables using the print statement:

Code Output
print("A", "B", "C") A B C
color = "blue"
print('The sky is', color)
The sky is blue

Python automatically separates each component using a space. By what if we don't want to use a space? What if we want to use a hyphen or a comma or nothing at all? Python has you covered.

The components which make up the print statement are called arguments. In the above examples, the string "I see", the variable number, the variable animal, and the string "running" are all arguments.

The print statement has a special argument which controls item separator:

Code Output Notes
print("A", "B", "C", sep="") ABC

We set the sep argument equal to an empty string. When the components were displayed, they ran together.

color = "blue"
print('The sky is', color, sep='')
The sky isblue

We set the sep argument equal to an empty string. When the components were displayed, they ran together.

You can use any string value for the sep argument:

Code Output Notes
print("A", "B", "C", sep="-") A-B-C

We set the sep argument equal to a hyphen.

print("A", "B", "C", sep="!!") A!!B!!C

We set the sep argument equal to two exclamation points.

print("A", "B", "C", sep="\n") A
B
C

We set the sep argument equal to a line break.

When you do not specify the sep argument, Python defaults to a space. When you want to use it, just separate it from the other components with a comma, then set your separator to whatever string you like.

End Behavior

We have also seen that the print statement automatically ends each statement with a line break.

Code Output
print("Line 1")
print("Line 2")
Line 1
Line 2
print("Line 1\nLine 2")
print("Line 3")
Line 1
Line 2
Line 3

The print statement also has an argument to control the end behavior:

Code Output Notes
print("Line 1", end=" ")
print("Line 2")
Line 1 Line 2

We set the end argument equal to a space of the first statement to a space and let the second one default. This ran the first and second statements together and separated them with a space. The second statement still ends with a line break.

print("Line 1", end="")
print("Line 2")
Line 1Line 2

We set the end argument equal to an empty string. Now they run together. The second statement still ends in a line break.

You can use any string for the end argument as well:

Code Output Notes
print("Line 1", end="\n\n")
print("Line 2")
Line 1

Line 2

Two line breaks

print("Line 1", end="\n\t~")
print("Line 2")
Line 1
~Line 2

Line break, tab, and a tilde

When you do not specify the end argument, Python defaults to a line break. When you want to use it, just separate it from the other components with a comma, then set your end argument to whatever string you like.

Using Them Together

You can use the sep and end arguments individually as needed or together. The order does not matter, so long as they follow your list of components. Here are some examples:

Code Output
print("Line 1", "Line 2", sep="!", end="")
print("Line 3")
Line 1!Line 2Line3
print("Line 1", "Line 2", end=" ", sep="\n")
print("Line 3")
Line 1
Line 2 Line 3

Launch Exercise

Formatting Numbers

We saw in the last lesson that numbers do not always display "prettily" when we want them to. For example, if we were to calculate the 4.75% tax on a $2.99 purchase we get:

Code Output
tax_rate = 0.0475
cost = 2.99
tax = 0.0475*2.99
print("You pay", tax, "in tax")
You pay 0.142025 in tax

Wait a minute! We can't pay $0.142025 in tax – we have no coin to represent fractions of a penny! It would make sense to round down to 0.14 and just display that. Fortunately, Python makes it easy for us to format numbers using the format function.

Just like the print statement, the format function accepts arguments. At the very least, it requires two: the number being formatted, and the format specifier. The format specifier is a special string which instructs Python on how to present the value. It is actually a whole language unto itself, but we'll display some of the more common examples.

Formatting Floats

Code Output
tax_rate = 0.0475
cost = 2.99
tax = 0.0475*2.99
print("You pay", format(tax, ".2f"), "in tax")
You pay 0.14 in tax

The code we used - format(tax, ".2f") – accepted the variable tax as the first argument. The second argument is the format specifier. The .2 represents the precision we want; in this case, 2 decimal places. The f represents the type of formatting we are performing. There is a whole library on the different types, but in this case f is for a fixed point number.

Note that format() will round up or down depending on the value of the next decimal place. If the number is greater than or equal to 5, it will round up. If the decimal is less than 5, it will round down.

Let's look at an estimation of the number pi and format it.

Code Result Notes
pi = 3.14159265359

none

We assign the approximate value of pi to the variable pi.

format(pi, ".0f") 3

.0 means no decimal places. Notice that this rounded down. The next number after 3 was a 1. 1 is less than 5, so it rounded down.

format(pi, ".1f") 3.1

.1 means one decimal place. Notice that this rounded down. The next number after 3.1 was a 4. 4 is less than 5, so it rounded down.

format(pi, ".2f") 3.14

.2 means two decimal places. Notice that this rounded down. The next number after 3.14 was a 1. 1 is less than 5, so it rounded down.

format(pi, ".3f") 3.142

.3 means three decimal places. Notice that this rounded up. The next number after 3.141 was a 5. 5 is greater than or equal to 5, so it rounded up to 3.142.

format(pi, ".4f") 3.1416

.4 means four decimal places. Notice that this rounded up. The next number after 3.1415 was a 9. 9 is greater than or equal to 5, so it rounded up to 3.1416

When you are dealing with large numbers, you might want to use a comma to separate the thousandths place like this: 14,726,986.19. We just need to add a comma to the format specifier:

Code Result
big_number = 14726986.192271

none

format(big_number, ",.0f") 14,726,986
format(big_number, ",.1f") 14,726,986.2
format(big_number, ",.2f") 14,726,986.19

Launch Exercise

Perhaps we want to format a percentage? In this case, we drop the f from the format specifier and replace it with a percentage sign %. Then we set our precision level to whatever we like:

Code Result
test_score = 0.754931

none

format(test_score, ".0%") 75%
format(test_score, ".1%") 75.5%
format(test_score, ".2%") 75.49%

You can even combine the comma formatting with the percentage:

Code Result
sales_increase = 74290.754931

none

format(sales_increase, ",.2%") 7,429,075.49%

Launch Exercise

Formatting Integers

Integers don't have decimal values as they are whole numbers. You can still use ,.0f to format a large integer, but it would be more proper to use d (for "decimal integer in base 10") instead of f. And since integers do not have decimal values, we can drop the precision. Look how these two different format specifiers produce identical results.

Code Result
cars = 10473

none

format(cars, ",.0f") 10,473
format(cars, ",d") 10,473

Launch Exercise

Debugging

When a syntax or runtime error occurs, the error message contains a lot of information, but it can be overwhelming. The most useful parts are usually:

  • What kind of error it was, and
  • Where it occurred.

Syntax errors are usually easy to find, but there are a few gotchas. Whitespace errors can be tricky because spaces and tabs are invisible and we are used to ignoring them.

>>> x = 5
>>> y = 6
  File "<stdin>", line 1
     y = 6
     ^
IndentationError: unexpected indent

In this example, the problem is that the second line is indented by one space. But the error message points to y, which is misleading. In general, error messages indicate where the problem was discovered, but the actual error might be earlier in the code, sometimes on a previous line.

The same is true of runtime errors. Suppose you are trying to compute a signal-to-noise ratio in decibels. The formula is SNRdb = 10 log10 (Psignal / Pnoise). In Python, you might write something like this:

import math
signal_power = 9
noise_power = 10
ratio = signal_power // noise_power
decibels = 10 * math.log10(ratio)
print(decibels)

When you run this program, you get an exception:

Traceback (most recent call last):
  File "snr.py", line 5, in ?
    decibels = 10 * math.log10(ratio)
ValueError: math domain error

The error message indicates line 5, but there is nothing wrong with that line. To find the real error, it might be useful to print the value of ratio, which turns out to be 0. The problem is in line 4, which uses floor division // instead of floating-point division /.

You should take the time to read error messages carefully, but don’t assume that everything they say is correct.